From 254cc6aca64c1a0005f15f8cab6dadcc55c33aa8 Mon Sep 17 00:00:00 2001 From: Cosimo Cecchi Date: Wed, 17 Nov 2010 21:38:22 +0100 Subject: [PATCH] open-with-widget: add a context menu for recommended entries We can put "Forget association" there, which removes the application from the recommended list. --- gtk/gtkopenwithwidget.c | 144 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 144 insertions(+) diff --git a/gtk/gtkopenwithwidget.c b/gtk/gtkopenwithwidget.c index fbe10e7cc7..696e793e12 100644 --- a/gtk/gtkopenwithwidget.c +++ b/gtk/gtkopenwithwidget.c @@ -124,6 +124,23 @@ refresh_and_emit_app_selected (GtkOpenWithWidget *self, self->priv->selected_app_info); } +static gboolean +path_is_heading (GtkTreeView *view, + GtkTreePath *path) +{ + GtkTreeIter iter; + GtkTreeModel *model; + gboolean res; + + model = gtk_tree_view_get_model (view); + gtk_tree_model_get_iter (model, &iter, path); + gtk_tree_model_get (model, &iter, + COLUMN_HEADING, &res, + -1); + + return res; +} + static void program_list_selection_activated (GtkTreeView *view, GtkTreePath *path, @@ -133,6 +150,9 @@ program_list_selection_activated (GtkTreeView *view, GtkOpenWithWidget *self = user_data; GtkTreeSelection *selection; + if (path_is_heading (view, path)) + return; + selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (self->priv->program_list)); refresh_and_emit_app_selected (self, selection); @@ -141,6 +161,111 @@ program_list_selection_activated (GtkTreeView *view, self->priv->selected_app_info); } +static void +item_forget_association_cb (GtkMenuItem *item, + gpointer user_data) +{ + GtkOpenWithWidget *self = user_data; + GtkTreePath *path = NULL; + GtkTreeIter iter; + GtkTreeModel *model; + GAppInfo *info; + + gtk_tree_view_get_cursor (GTK_TREE_VIEW (self->priv->program_list), &path, NULL); + model = gtk_tree_view_get_model (GTK_TREE_VIEW (self->priv->program_list)); + + if (path != NULL) + { + gtk_tree_model_get_iter (model, &iter, path); + gtk_tree_model_get (model, &iter, + COLUMN_APP_INFO, &info, + -1); + + if (info != NULL && g_app_info_can_remove_supports_type (info)) + g_app_info_remove_supports_type (info, self->priv->content_type, NULL); + } + + _gtk_open_with_widget_refilter (self); +} + +static GtkWidget * +gtk_open_with_widget_build_popup_menu (GtkOpenWithWidget *self) +{ + GtkWidget *menu; + GtkWidget *item; + + menu = gtk_menu_new (); + + item = gtk_menu_item_new_with_label (_("Forget association")); + g_signal_connect (item, "activate", + G_CALLBACK (item_forget_association_cb), self); + gtk_widget_show (item); + + gtk_menu_shell_append (GTK_MENU_SHELL (menu), item); + + return menu; +} + +static gboolean +should_show_menu (GtkOpenWithWidget *self, + GdkEventButton *event) +{ + GtkTreeIter iter; + GtkTreePath *path; + GtkTreeModel *model; + gboolean recommended, retval; + GAppInfo *info; + + gtk_tree_view_get_path_at_pos (GTK_TREE_VIEW (self->priv->program_list), + event->x, event->y, + &path, NULL, NULL, NULL); + + model = gtk_tree_view_get_model (GTK_TREE_VIEW (self->priv->program_list)); + gtk_tree_model_get_iter (model, &iter, path); + + gtk_tree_model_get (model, &iter, + COLUMN_RECOMMENDED, &recommended, + COLUMN_APP_INFO, &info, + -1); + + retval = recommended && (info != NULL); + + gtk_tree_path_free (path); + + if (info != NULL) + g_object_unref (info); + + return retval; +} + +static void +do_popup_menu (GtkOpenWithWidget *self, + GdkEventButton *event) +{ + GtkWidget *menu; + + if (!should_show_menu (self, event)) + return; + + menu = gtk_open_with_widget_build_popup_menu (self); + gtk_menu_attach_to_widget (GTK_MENU (menu), self->priv->program_list, NULL); + gtk_menu_popup (GTK_MENU (menu), NULL, NULL, NULL, NULL, + event->button, event->time); +} + +static gboolean +program_list_button_press_event_cb (GtkWidget *treeview, + GdkEventButton *event, + gpointer user_data) +{ + GtkOpenWithWidget *self = user_data; + + if (event->button == 3 && event->type == GDK_BUTTON_PRESS) + do_popup_menu (self, event); + + return FALSE; +} + static gboolean gtk_open_with_search_equal_func (GtkTreeModel *model, int column, @@ -218,6 +343,7 @@ gtk_open_with_sort_func (GtkTreeModel *model, gpointer user_data) { gboolean a_recommended, b_recommended; + gboolean a_heading, b_heading; gchar *a_name, *b_name, *a_casefold, *b_casefold; gint retval; @@ -230,11 +356,13 @@ gtk_open_with_sort_func (GtkTreeModel *model, gtk_tree_model_get (model, a, COLUMN_NAME, &a_name, COLUMN_RECOMMENDED, &a_recommended, + COLUMN_HEADING, &a_heading, -1); gtk_tree_model_get (model, b, COLUMN_NAME, &b_name, COLUMN_RECOMMENDED, &b_recommended, + COLUMN_HEADING, &b_heading, -1); /* the recommended one always wins */ @@ -250,6 +378,19 @@ gtk_open_with_sort_func (GtkTreeModel *model, goto out; } + /* they're both recommended or not, so if one is a heading, wins */ + if (a_heading) + { + return -1; + goto out; + } + + if (b_heading) + { + return 1; + goto out; + } + a_casefold = a_name != NULL ? g_utf8_casefold (a_name, -1) : NULL; b_casefold = b_name != NULL ? @@ -705,6 +846,9 @@ gtk_open_with_widget_init (GtkOpenWithWidget *self) g_signal_connect (self->priv->program_list, "row-activated", G_CALLBACK (program_list_selection_activated), self); + g_signal_connect (self->priv->program_list, "button-press-event", + G_CALLBACK (program_list_button_press_event_cb), + self); } static GAppInfo * -- 2.30.2